
#define PI			3.1415926


// Spherical //

vec2 CartesianToSpherical(in vec3 vNormal)
{
	vec2	spherical;

	spherical.x = atan(vNormal.y, vNormal.x) /PI;
	spherical.y = vNormal.z;

	return spherical * 0.5 + 0.5;
}

vec3 SphericalToCartesian(in vec2 vSpherical)
{
	vec2	sinCosTheta,
			sinCosPhi;

	vSpherical = vSpherical * 2.0 - 1.0;
	sinCosTheta.x = sin( vSpherical.x * PI );
	sinCosTheta.y = cos( vSpherical.x * PI );
	sinCosPhi = vec2( sqrt( 1.0 - vSpherical.y * vSpherical.y ), vSpherical.y );

	return vec3( sinCosTheta.y * sinCosPhi.x, sinCosTheta.x * sinCosPhi.x, sinCosPhi.y );    
}


void CalcNormalZ(inout vec3 vNormal)
{
	vNormal.z = sqrt( 1.0 - vNormal.x*vNormal.x - vNormal.y*vNormal.y );
}


// CryTeck version //

vec2 EncodeNormal(in vec3 vNormal)
{
	return ( normalize( vNormal.xy ) * sqrt( vNormal.z*0.5 + 0.5 ) );
}

vec3 DecodeNormal(in vec2 vNormal)
{
	vec3	normal;
	normal.z  = length( vNormal ) * 2.0 - 1.0;
	normal.xy = normalize( vNormal ) * sqrt( 1.0 - normal.z*normal.z );
	return normal;
}


// Stalker version //

vec2 PackNormal(in vec3 vNormal)
{
	vec2	res = ( vNormal.xy + vec2(1.0) ) * 0.5;
	res.x *= ( vNormal.z < 0.0 ? -1.0 : 1.0 );
	return res;
}

vec3 UnpackNormal(in vec2 vNormal)
{
	vec3	res;
	res.xy = ( abs(vNormal) * 2.0 ) - 1.0;
	res.z  = ( vNormal.x < 0.0 ? -1.0 : 1.0 ) * sqrt( abs( 1.0 - res.x*res.x - res.y*res.y ) );
	return res;
}
